const isWeex = typeof WXEnvironment !== 'undefined';
const isWeexIOS = isWeex && /ios/i.test(WXEnvironment.platform);
const isWeexAndroid = isWeex && !isWeexIOS;
import GLmethod from '../context-webgl/GLmethod';
const GCanvasModule = typeof weex !== 'undefined' && weex.requireModule ? weex.requireModule('gcanvas') : typeof __weex_require__ !== 'undefined' ? __weex_require__('@weex-module/gcanvas') : {};
let isDebugging = false;
let isComboDisabled = false;

const logCommand = function () {
  const methodQuery = [];
  Object.keys(GLmethod).forEach(key => {
    methodQuery[GLmethod[key]] = key;
  });

  const queryMethod = id => {
    return methodQuery[parseInt(id)] || 'NotFoundMethod';
  };

  const logCommand = (id, cmds) => {
    const mId = cmds.split(',')[0];
    const mName = queryMethod(mId);
    console.log(`=== callNative - componentId:${id}; method: ${mName}; cmds: ${cmds}`);
  };

  return logCommand;
}();

function joinArray(arr, sep) {
  let res = '';

  for (let i = 0; i < arr.length; i++) {
    if (i !== 0) {
      res += sep;
    }

    res += arr[i];
  }

  return res;
}

const commandsCache = {};
const GBridge = {
  callEnable: (ref, configArray) => {
    commandsCache[ref] = [];
    return GCanvasModule.enable({
      componentId: ref,
      config: configArray
    });
  },
  callEnableDebug: () => {
    isDebugging = true;
  },
  callEnableDisableCombo: () => {
    isComboDisabled = true;
  },
  callSetContextType: function (componentId, context_type) {
    GCanvasModule.setContextType(context_type, componentId);
  },
  callReset: function (id) {
    GCanvasModule.resetComponent && canvasModule.resetComponent(componentId);
  },
  render: isWeexIOS ? function (componentId) {
    return GCanvasModule.extendCallNative({
      contextId: componentId,
      type: 0x60000001
    });
  } : function (componentId) {
    return callGCanvasLinkNative(componentId, 0x60000001, 'render');
  },
  render2d: isWeexIOS ? function (componentId, commands, callback) {
    if (isDebugging) {
      console.log('>>> >>> render2d ===');
      console.log('>>> commands: ' + commands);
    }

    GCanvasModule.render([commands, callback ? true : false], componentId, callback);
  } : function (componentId, commands, callback) {
    if (isDebugging) {
      console.log('>>> >>> render2d ===');
      console.log('>>> commands: ' + commands);
    }

    callGCanvasLinkNative(componentId, 0x20000001, commands);

    if (callback) {
      callback();
    }
  },
  callExtendCallNative: isWeexIOS ? function (componentId, cmdArgs) {
    throw 'should not be here anymore ' + cmdArgs;
  } : function (componentId, cmdArgs) {
    throw 'should not be here anymore ' + cmdArgs;
  },
  flushNative: isWeexIOS ? function (componentId) {
    const cmdArgs = joinArray(commandsCache[componentId], ';');
    commandsCache[componentId] = [];

    if (isDebugging) {
      console.log('>>> >>> flush native ===');
      console.log('>>> commands: ' + cmdArgs);
    }

    const result = GCanvasModule.extendCallNative({
      "contextId": componentId,
      "type": 0x60000000,
      "args": cmdArgs
    });
    const res = result && result.result;

    if (isDebugging) {
      console.log('>>> result: ' + res);
    }

    return res;
  } : function (componentId) {
    const cmdArgs = joinArray(commandsCache[componentId], ';');
    commandsCache[componentId] = [];

    if (isDebugging) {
      console.log('>>> >>> flush native ===');
      console.log('>>> commands: ' + cmdArgs);
    }

    const result = callGCanvasLinkNative(componentId, 0x60000000, cmdArgs);

    if (isDebugging) {
      console.log('>>> result: ' + result);
    }

    return result;
  },
  callNative: function (componentId, cmdArgs, cache) {
    if (isDebugging) {
      logCommand(componentId, cmdArgs);
    }

    commandsCache[componentId].push(cmdArgs);

    if (!cache || isComboDisabled) {
      return GBridge.flushNative(componentId);
    } else {
      return undefined;
    }
  },

  texImage2D(componentId, ...args) {
    if (isWeexIOS) {
      if (args.length === 6) {
        const [target, level, internalformat, format, type, image] = args;
        GBridge.callNative(componentId, GLmethod.texImage2D + ',' + 6 + ',' + target + ',' + level + ',' + internalformat + ',' + format + ',' + type + ',' + image.src);
      } else if (args.length === 9) {
        const [target, level, internalformat, width, height, border, format, type, image] = args;
        GBridge.callNative(componentId, GLmethod.texImage2D + ',' + 9 + ',' + target + ',' + level + ',' + internalformat + ',' + width + ',' + height + ',' + border + ',' + +format + ',' + type + ',' + (image ? image.src : 0));
      }
    } else if (isWeexAndroid) {
      if (args.length === 6) {
        const [target, level, internalformat, format, type, image] = args;
        GCanvasModule.texImage2D(componentId, target, level, internalformat, format, type, image.src);
      } else if (args.length === 9) {
        const [target, level, internalformat, width, height, border, format, type, image] = args;
        GCanvasModule.texImage2D(componentId, target, level, internalformat, width, height, border, format, type, image ? image.src : 0);
      }
    }
  },

  texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image) {
    if (isWeexIOS) {
      if (arguments.length === 8) {
        GBridge.callNative(componentId, GLmethod.texSubImage2D + ',' + 6 + ',' + target + ',' + level + ',' + xoffset + ',' + yoffset, +',' + format + ',' + type + ',' + image.src);
      }
    } else if (isWeexAndroid) {
      GCanvasModule.texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image.src);
    }
  },

  bindImageTexture(componentId, src, imageId) {
    GCanvasModule.bindImageTexture([src, imageId], componentId);
  },

  perloadImage([url, id], callback) {
    GCanvasModule.preLoadImage([url, id], function (image) {
      image.url = url;
      image.id = id;
      callback(image);
    });
  },

  measureText(text, fontStyle, componentId) {
    return GCanvasModule.measureText([text, fontStyle], componentId);
  },

  getImageData(componentId, x, y, w, h, callback) {
    GCanvasModule.getImageData([x, y, w, h], componentId, callback);
  },

  putImageData(componentId, data, x, y, w, h, callback) {
    GCanvasModule.putImageData([x, y, w, h, data], componentId, callback);
  },

  toTempFilePath(componentId, x, y, width, height, destWidth, destHeight, fileType, quality, callback) {
    GCanvasModule.toTempFilePath([x, y, width, height, destWidth, destHeight, fileType, quality], componentId, callback);
  }

};
export default GBridge;